package com.chaihu.api.service.impl;

import com.alibaba.fastjson.JSON;
import com.chaihu.api.service.ApiService;
import com.chaihu.bean.entity.center.AppRoute;
import com.chaihu.bean.entity.center.AppService;
import com.chaihu.bean.enums.MsgCode;
import com.chaihu.bean.result.ResponseResult;
import com.chaihu.core.base.constants.CommonConstant;
import com.chaihu.core.cache.AppRouteCache;
import com.chaihu.core.cache.MappingCache;
import com.chaihu.core.client.RestTemplate;
import com.chaihu.core.context.ApiDataFlow;
import com.chaihu.core.event.service.api.ServiceDataFlowEventPublishing;
import com.chaihu.core.factory.AuthenticationFactory;
import com.chaihu.core.factory.DataFlowFactory;
import com.chaihu.core.factory.GenerateCodeFactory;
import com.chaihu.utils.constant.MappingConstant;
import com.chaihu.utils.constant.ResponseConstant;
import com.chaihu.utils.exception.BusinessException;
import com.chaihu.utils.exception.DecryptException;
import com.chaihu.utils.exception.InitConfigDataException;
import com.chaihu.utils.exception.NoAuthorityException;
import com.chaihu.utils.util.DateUtil;
import com.chaihu.utils.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author chaihu
 * @date 2021/10/13
 */
@Slf4j
@Service
public class ApiServiceImpl implements ApiService {
    @Autowired
    private RestTemplate restTemplate;

    @Override
    public ResponseEntity<String> service(String reqJson, Map<String, String> headers) throws BusinessException {
        ApiDataFlow dataFlow = null;

        //JSONObject responseJson = null;

        ResponseEntity<String> responseEntity = null;

        Date startDate = DateUtil.getCurrentDate();

        String resJson = "";

        try {
            //在post和 put 时才存在报文加密的情况
            if ("POST,PUT".contains(headers.get(CommonConstant.HTTP_METHOD))) {
                reqJson = decrypt(reqJson, headers);
            }

            //1.0 创建数据流 appId serviceCode
            dataFlow = DataFlowFactory.newInstance(ApiDataFlow.class).builder(reqJson, headers);
            log.info(JSON.toJSONString(dataFlow));

            //2.0 加载配置信息
            initConfigData(dataFlow);

            //3.0 校验 APPID是否有权限操作serviceCode
            judgeAuthority(dataFlow);

            //6.0 调用下游系统
            invokeBusinessSystem(dataFlow);

            responseEntity = dataFlow.getResponseEntity();

        } catch (DecryptException e) { //解密异常
            ResponseResult result = new ResponseResult(MsgCode.ERROR.getCode(), "解密异常：" + e.getMessage());
            responseEntity = new ResponseEntity<String>(JSON.toJSONString(result), HttpStatus.OK);
        } catch (BusinessException e) {
            ResponseResult result = new ResponseResult(MsgCode.ERROR.getCode(), e.getMessage());
            responseEntity = new ResponseEntity<String>(JSON.toJSONString(result), HttpStatus.OK);
        } catch (NoAuthorityException e) {
            ResponseResult result = new ResponseResult(MsgCode.ERROR.getCode(), "鉴权失败：" + e.getMessage());
            responseEntity = new ResponseEntity<String>(JSON.toJSONString(result), HttpStatus.OK);
        } catch (InitConfigDataException e) {
            ResponseResult result = new ResponseResult(MsgCode.ERROR.getCode(), "初始化失败：" + e.getMessage());
            responseEntity = new ResponseEntity<String>(JSON.toJSONString(result), HttpStatus.OK);
        } catch (Exception e) {
            log.error("内部异常：", e);
            ResponseResult result = new ResponseResult(MsgCode.ERROR.getCode(), "内部异常：" + e.getMessage() + e.getLocalizedMessage());
            responseEntity = new ResponseEntity<String>(JSON.toJSONString(result), HttpStatus.OK);
        } finally {
            Date endDate = DateUtil.getCurrentDate();

            if (dataFlow != null) {
                dataFlow.setEndDate(endDate);
            }
            if (responseEntity == null) {
                //resJson = encrypt(responseJson.toJSONString(),headers);
                responseEntity = new ResponseEntity<String>(resJson, HttpStatus.OK);
            }

            return responseEntity;
        }
    }

    /**
     * 解密
     *
     * @param reqJson
     * @return
     */
    private String decrypt(String reqJson, Map<String, String> headers) throws DecryptException {
        try {
            if (MappingConstant.VALUE_ON.equals(headers.get(CommonConstant.ENCRYPT))) {
                log.debug("解密前字符：" + reqJson);
                reqJson = new String(AuthenticationFactory.decrypt(reqJson.getBytes("UTF-8"),
                        AuthenticationFactory.loadPrivateKey(MappingConstant.KEY_PRIVATE_STRING)
                        , NumberUtils.isNumber(headers.get(CommonConstant.ENCRYPT_KEY_SIZE)) ?
                                Integer.parseInt(headers.get(CommonConstant.ENCRYPT_KEY_SIZE)) :
                                Integer.parseInt(MappingCache.getValue(MappingConstant.KEY_DEFAULT_DECRYPT_KEY_SIZE))), "UTF-8");
                log.debug("解密后字符：" + reqJson);
            }
        } catch (Exception e) {
            throw new DecryptException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR, "解密失败");
        }

        return reqJson;
    }

    /**
     * 2.0初始化配置信息
     *
     * @param dataFlow
     */
    private void initConfigData(ApiDataFlow dataFlow) {
//        Date startDate = DateUtil.getCurrentDate();
//        //查询配置信息，并将配置信息封装到 dataFlow 对象中
//        List<AppRoute> appRoutes = AppRouteCache.getAppRoute(dataFlow.getAppId());
//
//        if (appRoutes == null) {
//            //添加耗时
//            DataFlowFactory.addCostTime(dataFlow, "initConfigData", "加载配置耗时", startDate);
//            throw new InitConfigDataException(ResponseConstant.RESULT_CODE_INNER_ERROR, "当前没有获取到AppId对应的信息，appId = " + dataFlow.getAppId());
//        }
//        for (AppRoute appRoute : appRoutes) {
//            dataFlow.addAppRoutes(appRoute);
//        }
//        //
//        if ("-1".equals(dataFlow.getDataFlowId()) || StringUtil.isNullOrNone(dataFlow.getDataFlowId())) {
//            try {
//                dataFlow.setDataFlowId(GenerateCodeFactory.getDataFlowId());
//            }catch (Throwable e){
//                log.error("获取id失败",e);
//            }
//        }
//
//        //添加耗时
//        DataFlowFactory.addCostTime(dataFlow, "initConfigData", "加载配置耗时", startDate);
    }

    /**
     * 3.0判断 AppId 是否 有serviceCode权限
     *
     * @param dataFlow
     * @throws RuntimeException
     */
    private void judgeAuthority(ApiDataFlow dataFlow) throws NoAuthorityException {
        // TODO
    }

    /**
     * 6.0 调用下游系统
     *
     * @param dataFlow
     * @throws BusinessException
     */
    private void invokeBusinessSystem(ApiDataFlow dataFlow) throws BusinessException {
        Date startDate = DateUtil.getCurrentDate();
        //拿到当前服务
//        AppService appService = DataFlowFactory.getService(dataFlow, dataFlow.getRequestHeaders().get(CommonConstant.HTTP_SERVICE));
        AppService appService = null;
                // TODO
        dataFlow.setApiCurrentService(dataFlow.getRequestHeaders().get(CommonConstant.HTTP_SERVICE));
        ServiceDataFlowEventPublishing.multicastEvent(dataFlow, appService);
        DataFlowFactory.addCostTime(dataFlow, "invokeBusinessSystem", "调用下游系统耗时", startDate);
    }
}
